package com.kinsin.kinsinutil

import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.content.pm.*
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Build
import android.provider.Settings
import android.util.Log
import androidx.annotation.RequiresApi
import androidx.core.content.pm.PackageInfoCompat
import androidx.core.net.toUri
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.concurrent.TimeUnit

/**
 * 高级应用管理工具类
 * 功能包含：应用信息查询、启动管理、权限检查、安装状态监控等
 * 需要权限：
 * <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"/>
 * <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
 */
object AppUtils {

    /**
     * 增强版应用信息数据类
     * @property installTime 应用安装时间（毫秒）
     * @property minSdkVersion 应用支持的最低SDK版本
     */
    data class InstalledAppInfo(
        val packageName: String,
        val appName: String,
        val icon: Drawable?,
        val isSystemApp: Boolean,
        val versionName: String,
        val versionCode: Long,
        val installTime: Long,
        val minSdkVersion: Int,
        var isDisabled: Boolean = false
    )

    // region 核心方法
    //================================================================================

    /**
     * 获取已安装应用列表（增强版）
     * @param filter 自定义过滤条件
     */
    fun getInstalledApps(
        context: Context,
        includeSystemApp: Boolean = false,
        includeDisabled: Boolean = true,
        filter: (InstalledAppInfo) -> Boolean = { true }
    ): List<InstalledAppInfo> {
        val pm = context.packageManager
        return pm.getInstalledApplications(PackageManager.MATCH_ALL).mapNotNull { appInfo ->
            runCatching {
                val packageInfo = pm.getPackageInfoCompat(appInfo.packageName)
                val isSystem = appInfo.isSystemApp()

                if (!includeSystemApp && isSystem) return@mapNotNull null

                InstalledAppInfo(
                    packageName = appInfo.packageName,
                    appName = appInfo.loadLabel(pm).toString(),
                    icon = appInfo.loadIcon(pm),
                    isSystemApp = isSystem,
                    versionName = packageInfo.versionName.orEmpty(),
                    versionCode = packageInfo.safeVersionCode(),
                    installTime = packageInfo.firstInstallTime,
                    minSdkVersion = appInfo.minSdkVersion(),
                    isDisabled = !appInfo.enabled
                ).takeIf { (includeDisabled || !it.isDisabled) && filter(it) }
            }.onFailure { logW("Package info error: ${it.message}") }.getOrNull()
        }
    }

    /**
     * 异步获取应用列表（协程优化版）
     */
    suspend fun getInstalledAppsAsync(
        context: Context,
        includeSystemApp: Boolean = false,
        dispatcher: CoroutineDispatcher = Dispatchers.IO
    ): Result<List<InstalledAppInfo>> = runCatching {
        withContext(dispatcher) {
            getInstalledApps(context, includeSystemApp).map {
                it.copy(isDisabled = isAppDisabled(context, it.packageName))
            }
        }
    }
    // endregion

    // region 应用状态管理
    //================================================================================

    /**
     * 判断应用是否被禁用（增强版）
     */
    fun isAppDisabled(context: Context, packageName: String): Boolean {
        return runCatching {
            when (context.packageManager.getApplicationEnabledSetting(packageName)) {
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER,
                PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED -> true
                else -> false
            }
        }.getOrElse {
            logW("Enable check failed: ${it.message}")
            false
        }
    }

    /**
     * 检查应用是否安装（支持多版本）
     */
    fun isAppInstalled(context: Context, packageName: String): Boolean {
        return runCatching {
            context.packageManager.getPackageInfoCompat(packageName) != null
        }.getOrElse { false }
    }
    // endregion

    // region 应用操作
    //================================================================================

    /**
     * 安全启动应用
     * @return 启动结果和异常类型 Pair
     */
    fun launchApp(context: Context, packageName: String): Pair<Boolean, Exception?> {
        return runCatching {
            val intent = context.packageManager.getLaunchIntentForPackage(packageName)
                ?: throw ActivityNotFoundException("No launch intent")

            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            context.startActivity(intent)
            true to null
        }.recover { throwable ->
            val exception = throwable as? Exception ?: return@recover false to null
            when (exception) {
                is SecurityException -> logE("Launch permission denied")
                is ActivityNotFoundException -> logE("Activity not found")
            }
            false to exception
        }.getOrThrow()
    }

    /**
     * 安全打开浏览器
     */
    fun openBrowser(context: Context, url: String): Boolean {
        return runCatching {
            val uri = url.toUri().validateScheme()
            Intent(Intent.ACTION_VIEW).apply {
                data = uri
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                resolveActivity(context.packageManager)?.let {
                    context.startActivity(this)
                } ?: throw ActivityNotFoundException("No browser available")
            }
            true
        }.onFailure { logE("Browser open failed: ${it.message}") }.isSuccess
    }

    /**
     * 卸载应用（带结果回调）
     */
    fun uninstallApp(context: Context, packageName: String, callback: (Boolean) -> Unit) {
        runCatching {
            val intent = Intent(Intent.ACTION_DELETE).apply {
                data = Uri.parse("package:$packageName")
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            }
            context.startActivity(intent)
            callback(true)
        }.onFailure {
            logE("Uninstall failed: ${it.message}")
            callback(false)
        }
    }
    // endregion

    // region 扩展功能
    //================================================================================

    /**
     * 获取应用版本信息（安全兼容版）
     * @return Pair的first为版本名称（非null），second为版本号（兼容所有API）
     */
    fun getVersionInfo(context: Context, packageName: String): Pair<String, Long>? {
        return runCatching {
            val packageInfo = context.packageManager.getPackageInfoCompat(packageName)

            // 处理versionName为null的情况
            val safeVersionName = packageInfo.versionName ?: ""

            // 使用AndroidX兼容方法获取版本号
            val safeVersionCode = PackageInfoCompat.getLongVersionCode(packageInfo)

            safeVersionName to safeVersionCode
        }.recover { e ->
            when (e) {
                is PackageManager.NameNotFoundException -> {
                    logD("Package not found: $packageName")
                }
                is SecurityException -> {
                    logE("Permission denied for package: $packageName")
                }
                else -> {
                    logE("Unexpected error: ${e.javaClass.simpleName}")
                }
            }
            null
        }.getOrNull()
    }

    /**
     * 获取应用安装来源（需要API 30+）
     */
    @RequiresApi(Build.VERSION_CODES.R)
    fun getInstallSource(context: Context, packageName: String): String? {
        return runCatching {
            context.packageManager.getInstallSourceInfo(packageName).installingPackageName
        }.getOrNull()
    }

    /**
     * 检查权限状态（安全兼容版）
     * @param packageName 要检查的应用包名（默认当前应用）
     */
    fun checkPermission(
        context: Context,
        permission: String,
        packageName: String = context.packageName
    ): PermissionStatus {
        return when {
            // 检查是否已授予权限
            context.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED ->
                PermissionStatus.GRANTED

            // 检查权限是否被策略撤销（需API 23+）
            Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
                    context.packageManager.isPermissionRevokedByPolicy(permission, packageName) ->
                PermissionStatus.REVOKED_BY_POLICY

            else -> PermissionStatus.DENIED
        }
    }

    enum class PermissionStatus { GRANTED, DENIED, REVOKED_BY_POLICY }
    // endregion

    // region 扩展函数
    //================================================================================

    private fun PackageInfo.safeVersionCode() = PackageInfoCompat.getLongVersionCode(this)

    private fun ApplicationInfo.isSystemApp() = flags and ApplicationInfo.FLAG_SYSTEM != 0

    private fun ApplicationInfo.minSdkVersion(): Int = when {
        Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> minSdkVersion
        else -> targetSdkVersion
    }

    private fun Uri.validateScheme(): Uri {
        if (scheme !in setOf("http", "https")) throw SecurityException("Unsafe scheme: $scheme")
        return this
    }

    // 在工具类中添加以下扩展函数
    private fun PackageManager.getPackageInfoCompat(packageName: String): PackageInfo {
        return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
            getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0))
        } else {
            @Suppress("DEPRECATION")
            getPackageInfo(packageName, 0)
        }
    }
    // endregion

    // region 日志工具
    //================================================================================

    private fun logE(message: String) = Log.e("AppUtils", message)
    private fun logW(message: String) = Log.w("AppUtils", message)
    private fun logD(message: String) = Log.d("AppUtils", message)
    // endregion
}